Basic Multilingual Plane, BMP
Supplementary Multilingual Plane

1 基本概念

  • 字符:各种文字和符号的统称,包括各国各族各地的文字,标点符号,图形符号,数字等。
  • 字符集: 字符的集合,比如汉字字符集,ASCII字符集,简体中文字符集,罗马字母等。字符集关心的是这个集合需要包含哪些东西,怎么唯一表示这个集合中的每一个元素。
  • 字符编码: 将字符集处理为计算机能够识别和处理的规则。字符编码关注一个字符如何用二进制表示,如何让计算机精确识别。
  • 内码: 内码是指计算机汉字系统中使用的二进制字符编码,是沟通输入、输出与系统平台之间的交换码,通过内码可以达到通用和高效率传输文本的目的。比如MS Word中所存储和调用的就是内码而非图形文字。英文ASCII字符采用一个字节的内码表示,中文字符如国标字符集中,GB2312、GB12345、GB13000皆用双字节内码,GB18030(27,533汉字)双字节内码汉字为20,902个,其余6,631个汉字用四字节内码。
  • 编码操作: 将信息转换为二进制串的过程。
  • 解码操作: 将字符从二进制串中还原的操作。

2 常见字符集

  • ASCII: ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是基于罗马字母表的一套电脑编码系统。用7位二进制来表示字符,共128个字符。同 ISO 646,ASCII字符集包括英文字母、阿拉伯数字和标点符号等字符。。
  • 扩展ASCII:用8位二进制来表示字符,共256个.ASCII扩展字符集比ASCII字符集扩充出来的符号包括表格符号、计算符号、希腊字母和特殊的拉丁符号。
  • ISO 8859-* ASCII收录了空格及94个“可印刷字符”,足以给英语使用。
    但是,其他使用拉丁字母的语言(主要是欧洲国家的语言),都有一定数量的变音字母,故可以使用ASCII及控制字符以外的区域来储存及表示。
    除了使用拉丁字母的语言外,使用西里尔字母的东欧语言、希腊语、泰语、现代阿拉伯语、希伯来语等,都可以使用这个形式来储存及表示。
  • GB2312: GB2312是中国国家标准的简体中文字符集。它所收录的汉字已经覆盖99.75%的使用频率,基本满足了汉字的计算机处理需要。在中国大陆和新加坡获广泛使用。字符集中除常用简体汉字字符外还包括希腊字母、日文平假名及片假名字母、俄语西里尔字母等字符,未收录繁体中文汉字和一些生僻字。
  • GBK: GBK是GB2312的扩展,是向上兼容的,因此GB2312中的汉字的编码与GBK中汉字的相同。GBK编码是GB2312编码的超集,向下完全兼容GB2312,同时GBK收录了Unicode基本多文种平面中的所有CJK汉字。同 GB2312一样,GBK也支持希腊字母、日文假名字母、俄语字母等字符,但不支持韩语中的表音字符(非汉字字符)。GBK还收录了GB2312不包含的汉字部首符号、竖排标点符号等字符。
  • BIG5: Big5收录的汉字只包括繁体汉字,不包括简体汉字,一些生僻的汉字也没有收录。GBK收录的日文假名字符、俄文字符Big5也没有收录。因为Big5当中收录的字符有限,因此有很多在Big5基础上扩展的编码,如倚天中文系统。Windows系统上使用的代码页CP950也可以理解为是对Big5的扩展,在Big5的基础上增加了7个汉字和一些符号。Big5编码对应的字符集是GBK字符集的子集,也就是说Big5收录的字符是GBK收录字符的一部分,但相同字符的编码不同。
  • GB18030: GB 18030字符集标准解决汉字、日文假名、朝鲜语和中国少数民族文字组成的大字符集计算机编码问题。该标准的字符总编码空间超过150万个编码位,收录了27484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字。满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求。并且与Unicode 3.0版本兼容,填补Unicode扩展字符字汇“统一汉字扩展A”的内容。并且与以前的国家字符编码标准(GB2312,GB13000.1)兼容。
  • UCS: 通用字符集(Universal Character Set,UCS)是由ISO制定的ISO 10646(或称ISO/IEC 10646)标准所定义的字符编码方式,采用4字节编码。
    UCS包含了已知语言的所有字符。
    除了拉丁语、希腊语、斯拉夫语、希伯来语、阿拉伯语、亚美尼亚语、格鲁吉亚语,还包括中文、日文、韩文这样的象形文字,UCS还包括大量的图形、印刷、数学、科学符号。
  • Unicode字符集: Unicode字符集编码是Universal Multiple-Octet Coded Character Set 通用多八位编码字符集的简称,是由一个名为 Unicode 学术学会(Unicode Consortium)的机构制订的字符编码系统,支持现今世界各种不同语言的书面文本的交换、处理及显示。

3 编码方式(编码)

一种字符集,都会有与其对应的一个或多个编码方式,如下大的编码方式是跟上面的字符集对应的。

  • ASCII字符集: ASCII编码
  • ISO 8859-*字符集: ISO 8859-*编码
  • GB2313字符集: GB2312编码
  • BIG5字符集: BIG5编码
  • GB18030字符集: GB18030编码
  • UCS字符集: UCS-2编码,UCS-4编码
  • Unicode字符集:UTF-7,UTF-8编码,UTF-16编码,Unicode编码(UCS-2),Unicode大端,Unicode小端,UTF-32编码
  • ANSI: 使用2个字节来代表一个字符的各种汉字延伸编码方式,称为ANSI编码。 在简体中文系统下,ANSI编码代表GB2312编码,在日文操作系统下,ANSI编码代表JIS编码。

4 编码转换

Unicode是内存编码表示方案(是规范),而UTF是如何保存和传输Unicode的方案(是实现)
GBK、GB2312等与UTF8之间都必须通过Unicode编码才能相互转换:
GBK、GB2312--Unicode--UTF8
UTF8--Unicode--GBK、GB2312

5 字节序

UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?

为了识别 Unicode 文件,Microsoft 建议所有的 Unicode 文件应该以 ZERO WIDTH NOBREAK SPACE(U+FEFF)字符开头。这作为一个“特征符”或“字节顺序标记(byte-order mark,BOM)”来识别文件中使用的编码和字节顺序。

Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一个有点小聪明的想法:

在UCS编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE”的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符”ZERO WIDTH NO-BREAK SPACE”。

这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符”ZERO WIDTH NO-BREAK SPACE”又被称作BOM。

UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符”ZERO WIDTH NO-BREAK SPACE”的UTF-8编码是EF BB BF(读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。

6 编码识别

  • XML解析读取XML文档时,W3C定义了3条规则:
    • 如果文档中有BOM,就定义了文件编码;
    • 如果文档中没有BOM,就查看XML声明中的编码属性;
    • 如果上述两者都没有,就假定XML文档采用UTF-8编码。
  • 对于Unicode文本最标准的途径是检测文本最开头的几个字节。如:
    开头字节         Charset/encoding
    EF BB BF       UTF-8
    FE FF          UTF-16/UCS-2, little endian(UTF-16LE)
    FF FE          UTF-16/UCS-2, big endian(UTF-16BE)
    FF FE 00 00      UTF-32/UCS-4, little endian.
    00 00 FE FF      UTF-32/UCS-4, big-endia

7 汉字编码相关

英语文字是拼音文字,所有文字均由26个字母拼组而成,所以使用一个字节表示一个字符足够了。但汉字是象形文字,汉字的计算机处理技术比英文字符复杂得多,一般用两个字节表示一个汉字。由于汉字有一万多个,常用的也有六千多个,所以编码采用两字节的低7位共14个二进制位来表示。一般汉字的编码方案要解决4种编码问题。
(1)汉字交换码
汉字交换码主要是用作汉字信息交换的。以国家标准局1980年颁布的《信息交换用汉字编码字符集基本集》(代号为GB2312-80)规定的汉字交换码作为国家标准汉字编码,简称国标码。
国标GB 2312-80规定,所有的国际汉字和符号组成一个94×94的矩阵。在该矩阵中,每一行称为一个“区”,每一列称为一个“位”,这样就形成了94个区号(01~94)和94个位号(01~94)的汉字字符集。国标码中有6763个汉字和628个其他基本图形字符,共计7445个字符。其中规定一级汉字3755个,二级汉字3008个,图形符号682个。一个汉字所在的区号与位号简单地组合在一起就构成了该汉字的“区位码”。在汉字区位码中,高两位为区号,低两位为位号。因此,区位码与汉字或图形符号之间是一一对应的。一个汉字由两个字节代码表示。
(2)汉字机内码
汉字机内码又称内码或汉字存储码。该编码的作用是统一了各种不同的汉字输入码在计算机内的表示。汉字机内码是计算机内部存储、处理的代码。计算机既要处理汉字,又要处理英文,所以必须能区别汉字字符和英文字符。英文字符的机内码是最高位为0的8位ASCII码。为了区分,把国标码每个字节的最高位由0改为1,其余位不变的编码作为汉字字符的机内码。
一个汉字用两个字节的内码表示,计算机显示一个汉字的过程首先是根据其内码找到该汉字字库中的地址,然后将该汉字的点阵字型在屏幕上输出。
汉字的输入码是多种多样的,同一个汉字如果采用的编码方案不同,则输入码就有可能不一样,但汉字的机内码是一样的。有专用的计算机内部存储汉字使用的汉字内码,用以将输入时使用的多种汉字输入码统一转换成汉字机内码进行存储,以方便机内的汉字处理。在汉字输入时,根据输入码通过计算机或查找输入码表完成输入码到机内码的转换。如汉字国际码(H)+8080(H)=汉字机内码(H)。
(3)汉字输入码
汉字输入码也叫外码,是为了通过键盘字符把汉字输入计算机而设计的一种编码。
英文输入时,想输入什么字符便按什么键,输入码和内码是一致的。而汉字输入规则不同,可能要按几个键才能输入一个汉字。汉字和键盘字符组合的对应方式称为汉字输入编码方案。汉字外码是针对不同汉字输入法而言的,通过键盘按某种输入法进行汉字输入时,人与计算机进行信息交换所用的编码称为“汉字外码”。对于同一汉字而言,输入法不同,其外码也是不同的。例如,对于汉字“啊”,在区位码输入法中的外码是1601,在拼音输入中的外码是a,而在五笔字型输入法中的外码是KBSK。汉字的输入码种类繁多,大致有4种类型,即音码、形码、数字码和音形码。
(4)汉字字形码
汉字在显示和打印输出时,是以汉字字形信息表示的,即以点阵的方式形成汉字图形。汉字字形码是指确定一个汉字字形点阵的代码(汉字字形码)。一般采用点阵字形表示字符。
目前普遍使用的汉字字型码是用点阵方式表示的,称为“点阵字模码”。所谓“点阵字模码”,就是将汉字像图像一样置于网状方格上,每格是存储器中的一个位,16×16点阵是在纵向16点、横向16点的网状方格上写一个汉字,有笔画的格对应1,无笔画的格对应0。这种用点阵形式存储的汉字字型信息的集合称为汉字字模库,简称汉字字库。
通常汉字显示使用16×16点阵,而汉字打印可选用24×24点阵、32×32点阵、64×64点阵等。汉字字形点阵中的每个点对应一个二进制位,1字节又等于8个二进制位,所以16×16点阵字形的字要使用32个字节(16×16÷8字节=32字节)存储,64×64点阵的字形要使用512个字节。
在16×16点阵字库中的每一个汉字以32个字节存放,存储一、二级汉字及符号共8836个,需要282.5KB磁盘空间。而用户的文档假定有10万个汉字,却只需要200KB的磁盘空间,这是因为用户文档中存储的只是每个汉字(符号)在汉字库中的地址(内码)。

  • 区位码:
    在 GB2312 时提出的, GB2312 是一个 94*94 的二维表, 行就是 “区”、列就是 “位”, 譬如 “万” 字在 45 区 82 位, 所以 “万” 字的区位码是: 45 82.

00-09 区(682个): 是符号、数字、英文字符…制表符等;
10-15 区: 空白, 留待扩展;
16-55 区(3755个): 常用汉字(也有叫一级汉字), 按拼音排序;
56-87 区(3008个): 非常用汉字(也有叫二级汉字), 这是按部首排序的;
88-94 区: 空白, 留待扩展.

  • 国际码:区位码无法用于汉字通信,因为它可能与通信使用的控制码(00H1FH)(即031,还记得ASCII码特殊字符的范围吗?)发生冲突。于是ISO2022规定每个汉字的区号和位号必须分别加上32(即二进制数00100000,16进制20H),得到对应的国标交换码,简称国标码,交换码。
    这样我们可以算出(45+32, 82+32):
    “万” 字的国际码是 77 114($4D72)

77 = 0111 0111
114 = 0111 0010

77和114这两个字节还是以0开头,所以还是不能用于ANSI编码里,否则很难分清你到底是要一个“万”字,还是要M和r这两个英文字符。

  • 内码:
    由于文本中通常混合使用汉字和西文字符,汉字信息如果不予以特别标识,就会与单字节的ASCII码混淆。此问题的解决方法之一是将一个汉字看成是两个扩展ASCII码,使表示GB2312汉字的两个字节的最高位都为1。即国标码加上128(即二进制数10000000,16进制80H)这种高位为1的双字节汉字编码即为GB2312汉字的机内码,简称为内码。20H+80H=A0H。这也就是常说的在区位码的区号和位号上分别加上A0H就得到了GB2312编码的由来。

77 + 128 = 205 = CD
114+ 128 = 242 = F2

打开记事本输入 “万” 字,保存(编码选择 ANSI); 然后用二进制编辑器(譬如: UltraEdit) 打开, 会看到: CD F2, 这就是 “万” 字的内码! (当然,已经在计算机里处理了,以最实用的标准为准;而之前两种编码都只是理论上的标准)

总结一下: 从区位码(国家标准定义) —> 区和位分别 +32 得到国际码(不再国际混淆)—> 再分别 +128 得到内码(与ACSII也不再混淆); 区位码的区和位分别 +160 即可得到内码。用十六进制表示: 区位码 + $A0A0 = 内码。
ASCII中032、127共34个是需要兼容的,所以国标码前面应该空出33个编码,区位码是从0194(不是从00开始的哟),所以加32(而非33),空出0~32这33个位置

内码输入法状态下:可以同时用区位码和内码输出,但不能用国标码输出!
用户—汉字输入码—键盘—键盘扫描码—BIOS键盘驱动程序—-ASCII码—-汉字输入软件—-汉字内码

计算机中汉字的表示也是用二进制编码,同样是人为编码的。根据应用目的的不同,汉字编码分为外码、交换码、机内码和字形码。

  • 1.外码(输入码)
    外码也叫输入码,是用来将汉字输入到计算机中的一组键盘符号。常用的输入码有拼音码、五笔字型码、自然码、表形码、认知码、区位码和电报码等,一种好的编码应有编码规则简单、易学好记、操作方便、重码率低、输入速度快等优点,每个人可根据自己的需要进行选择。
  • 2.交换码(国标码)
    计算机内部处理的信息,都是用二进制代码表示的,汉字也不例外。而二进制代码使用起来是不方便的,于是需要采用信息交换码。中国标准总局1981年制定了中华人民共和国国家标准GB2312–80《信息交换用汉字编码字符集–基本集》,即国标码。
    区位码是国标码的另一种表现形式,把国标GB2312–80中的汉字、图形符号组成一个94×94的方阵,分为94个“区”,每区包含94个“位”,其中“区”的序号由01至94,“位”的序号也是从01至94。94个区中位置总数=94×94=8836个,其中7445个汉字和图形字符中的每一个占一个位置后,还剩下1391个空位,这1391个位置空下来保留备用。
  • 3.机内码
    根据国标码的规定,每一个汉字都有了确定的二进制代码,在微机内部汉字代码都用机内码,在磁盘上记录汉字代码也使用机内码。
  • 4.汉字的字形码
    字形码是汉字的输出码,输出汉字时都采用图形方式,无论汉字的笔画多少,每个汉字都可以写在同样大小的方块中。通常用16×16点阵来显示汉字。
  • 5.汉字地址码
    汉字地址码是指汉字库中存储汉字字形信息的逻辑地址码。它与汉字内码有着简单的对应关系,以简化内码到地址码的转换。

8 参考

  1. 字符编码方式发展历程(强烈推荐)

  2. 字符,字节和编码

  3. 字符集和字符编码(Charset & Encoding)

  4. 字符集与字符集编码简介

  5. 字符编码详解

  6. 字节那些事儿

  7. 中文编码杂谈

  8. UNICODE与UTF-8的转换详解

  9. 字符集编码详解

  10. 常用字符集编码详解

  11. 深入了解字符集和编码问题

  12. 字符编码详解——彻底理解掌握编码知识,“乱码”不复存在

  13. Unicode 字符集与它的编码方式

  14. 字符集编码详解

  15. 各种字符集和编码详解

  16. 字符编解码的故事(ASCII,ANSI,Unicode,Utf-8)

  17. 实例详细介绍各种字符集编码转换问题

  18. 字符编码详解

  19. The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

  20. 十分钟搞清字符集和字符编码

  21. 遇到乱码不怕不怕啦——计算机字符编码详尽讲解

  22. 字符编码笔记:ASCII,Unicode和UTF-8

  23. 字符编码的奥秘

  24. 十分钟搞清字符集和字符编码

  25. 字符集编码发展简史

  26. 深入了解字符集和编码

  27. 谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词

  28. ANSI编码和Unicode编码的不同

  29. 各种编码UNICODE、UTF-8、ANSI、ASCII、GB2312、GBK详解

  30. 计算机内部编码

  31. 说说Unicode,UTF8,UTF16,BOM,Big endian,Little

  32. 字符编码深入解析

  33. 汉字的存储和编码

  34. 汉字在电脑中是如何存储与编码

  35. 区位码,国标码,内码之间的区别与联系,以及如何转换

  36. Unicode与JavaScript

  37. 彻底搞懂乱码——字符,字节和编码

  38. 彻底搞懂字符编码(unicode,mbcs,utf-8,utf-16,utf-32,big endian,little endian…)

  39. 带补充 彻底搞懂字符编码(unicode,mbcs,utf-8,utf-16,utf-32,big endian,little endian…)

× 赞赏这个人~
打赏二维码